package study.itwill.team5.house;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import study.itwill.common.DBHandler;
import study.itwill.common.DateTime;

/**
 * 민박 도시 - 추가, 수정, 삭제, 조회, 리스트(검색포함) 기능을 가진 클래스
 */
public class HouseCity {
	
	// Logger 클래스의 인스턴스를 받아온다.
	static Logger logger = Logger.getLogger(HouseCity.class);
		
	private static final String TABLE = "house_city";
	
	// 데이터베이스 제어 객체에 대한 참조
	DBHandler db = null;
	
	/** 현재시간 데이터 저장을 위한 SQL구문 작성 */
	String datetime = DateTime.getInstance().getNowDateTimeString();
	
	public HouseCity() {
		// DB객체에 대한 참조 연결
		db = DBHandler.getInstance();
	}

	/**
	 * 민박 도시 추가 기능
	 * 
	 * @param	city_name	- 도시이름
	 * @return	int			- 추가된 도시의 일련번호
	 */
	public int addCity(String city_name) {
		//-----------------------------------------
		// 메서드 시작
		//-----------------------------------------
		logger.debug("=============== method start >> addCity");
		logger.debug("[PARAMS] city_name=" + city_name);
		
		int seq = -1;
		
		// SQL 인젝션 방어
		city_name = city_name.replace("'", "\'");
		
		// 트랜젝션에 대한 판단이 잘 서지 않는다면, 무조건 하면 된다.
		db.beginTrans();
		
		// INSERT 처리를 위한 구현
		String sql = "INSERT INTO house_city("
	            + "city_name, reg_date, edit_date"
	            + ") VALUES ('%s', '%s', '%s');";
		
		
		boolean result = db.execSql(sql, city_name, datetime, datetime);
		
		//-----------------------------------------
		// 결과처리
		//-----------------------------------------
		if(result) {
			db.commit();
			seq = db.getMax(TABLE, "seq", null);
			logger.debug("처리결과 >> " + seq + "번 도시 추가 성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 도시 추가 실패");
		}
		
		logger.debug("=============== method end >> addCity");
		
		
		return seq;
	}

	/**
	 * 민박 도시 수정 기능
	 * @param	seq			- 도시 일련번호
	 * @param	city_name	- 도시이름
	 * @return boolean		- 수정 성공 - true, 수정 실패 - false
	 */
	public boolean editCity(int seq, String city_name) {
		logger.debug("=============== method start >> editCity");
		logger.debug("[PARAMS] seq=" + seq);
		logger.debug("[PARAMS] city_name=" + city_name);
		
		// SQL 인젝션 방어
		city_name = city_name.replace("'", "\'");
		
		boolean result = false;
		
		db.beginTrans();
		
		String sql = "UPDATE house_city "
				+ "SET city_name = '%s', edit_date = '%s' "
				+ "WHERE seq = %d;";
		
		result = db.execSql(sql, city_name, datetime, seq);
		
		if(result) {
			db.commit();
			logger.debug("처리결과 >> " + seq + "번 도시이름 수정성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 도시이름 수정 실패 ");
		}
		
		logger.debug("=============== method end >> editCity");
		
		return result;
		
	}

	/**
	 * 민박 도시 삭제 기능 (관리자)
	 * @param seq			- 민박도시 일련 번호
	 * @return boolean		- 삭제 성공 - true, 삭제 실패 - false
	 */
	public boolean deleteCity(int seq) {
		logger.debug("=============== method start >> deleteCity");
		logger.debug("[PARAMS] seq=" + seq);
		
		boolean result = false;
		
		// 이 데이터를 참조하는 다른 데이터들의 존재 여부 검사
		// SELECT COUNT(studno) FROM student WHERE profno=?
		if (db.getCount("seq", "house", "house_city_seq=" + seq) > 0) {
			logger.error("참조 무결성 위반");
			return result;
		}
		
		db.beginTrans();
		
		String sql = "DELETE FROM house_city WHERE seq = %d;";
		result = db.execSql(sql, seq);
		
		if(result) {
			db.commit();
			logger.debug("처리결과 >> " + seq + "번 도시 삭제 성공");
		} else {
			db.rollback();
			logger.error("처리결과 >> 도시 삭제 실패 ");
		}
		
		logger.debug("=============== method end >> deleteCity");
		
		return result;
	}
	
	/**
	 * 민박 도시 조회
	 * @param seq				- 민박도시 테이블 일련번호
	 * @return HouseCityItem	- 민박도시 한개의 정보를 객체로 리턴
	 */
	public HouseCityItem viewCity(int seq) {
		logger.debug("=============== method start >> viewCity");
		logger.debug("[PARAMS] seq=" + seq);
		
		HouseCityItem item = null;
		
		// 데이터 조회
		String sql = "SELECT seq, city_name, reg_date, edit_date "
				+ "FROM house_city "
				+ "WHERE seq = %d;";
		
		ResultSet rs = db.getResult(sql, seq);
		
		if(rs != null) {
			// 데이터 조회 결과 있는 경우
			try {
				rs.next();
				
				// 1) ResultSet의 모든 데이터를 변수로 추출
				int city_seq = rs.getInt(1);
				String city_name = rs.getString(2);
				String reg_date = rs.getString(3);
				String edit_date = rs.getString(4);
				
				// 2) 추출된 값을 객체로 구성
				item = new HouseCityItem(city_seq, city_name, reg_date, edit_date);
				
			} catch (SQLException e) {
				logger.error(e);
			} finally {
				// 3) 데이터 조회에 대한 메모리 반납
				try {
					rs.close();
				} catch (SQLException e) {}
				rs = null;
			}
		}
		
		if(item == null) {
			logger.error("데이터 조회 실패");
		} else {
			logger.debug("데이터 조회 성공");
			logger.debug(item.toString());
		}
				
		logger.debug("=============== method end >> viewCity");
		
		return item;
		
	}

	/**
	 * 민박 도시 리스트조회
	 * @param	choice						- 검색조건 (0:민박 도시 전체, 1:도시이름)
	 * @param	search						- 검색값
	 * @return	ArrayList<HouseCityItem>	- 민박 도시 전체 리스트 정보를 객체배열로 리턴
	 */
	public ArrayList<HouseCityItem> listCity(int choice, String search) {
		logger.debug("=============== method start >> listCity");
		logger.debug("[PARAMS] choice=" + choice);
		logger.debug("[PARAMS] search=" + search);
		
		ArrayList<HouseCityItem> list = null;
		
		String sql = null;
		
		/*
		 *  민박 도시 검색을 위한 파라미터 정의
		 *  0, null : 민박도시 전체리스트 검색
		 *  		(전체리스트 검색은 오버로딩 정의로 숫자값 하나만을 파라미터로 받을수 있다)
		 *  1, "도시이름 검색"
		 */
		switch(choice) {
		case 0:
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city;";
			break;
			
		case 1:
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city "
					+ "WHERE city_name like '%%" + search + "%%';";
			break;
		
			
		default:
			System.out.println("검색조건 선택이 올바르지 않습니다.");
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city "
					+ "WHERE seq=-1;";
			break;
		}
			
		
		ResultSet rs = db.getResult(sql);
		
		if(rs != null) {
			// 데이터 조회 결과 있는 경우
			try {
				list = new ArrayList<HouseCityItem>();
				
				while(rs.next()) {
					
					// 1) ResultSet의 모든 데이터를 변수로 추출
					int city_seq = rs.getInt(1);
					String city_name = rs.getString(2);
					String reg_date = rs.getString(3);
					String edit_date = rs.getString(4);
					
					// 2) 추출된 값을 객체로 구성
					HouseCityItem item = new HouseCityItem(city_seq, city_name, reg_date, edit_date);
					
					// 3) ArrayList에 추가
					list.add(item);
				}
			} catch (SQLException e) {
				logger.error(e);
			} finally {
				// 4) 데이터 조회에 대한 메모리 반납
				try {
					rs.close();
				} catch (SQLException e) {}
				rs = null;
			}
		}
		
		if(list == null) {
			logger.error("데이터 조회 실패");
		} else {
			logger.debug("데이터 조회 성공 >> " + list.size() + "건 조회됨");
		}
		
		logger.debug("=============== method end >> listCity");
		
		return list;
	}
	
	/**
	 * 민박 도시 리스트조회
	 * @param	choice						- 검색조건 (0:민박 도시 전체, 1:도시이름)
	 * @param	search						- 검색값
	 * @param	start						- 검색 범위의 시작위치
	 * @param	end							- 한 페이지에 보여질 글의 목록 수
	 * @return	ArrayList<HouseCityItem>	- 민박 도시 전체 리스트 정보를 객체배열로 리턴
	 */
	public ArrayList<HouseCityItem> listCity(int choice, String search, int start, int end) {
		logger.debug("=============== method start >> listCity");
		logger.debug("[PARAMS] choice=" + choice);
		logger.debug("[PARAMS] search=" + search);
		logger.debug("[PARAMS] start=" + start);
		logger.debug("[PARAMS] end=" + end);
		
		ArrayList<HouseCityItem> list = null;
		
		String sql = null;
		
		/*
		 *  민박 도시 검색을 위한 파라미터 정의
		 *  0, null : 민박도시 전체리스트 검색
		 *  		(전체리스트 검색은 오버로딩 정의로 숫자값 하나만을 파라미터로 받을수 있다)
		 *  1, "도시이름 검색"
		 */
		switch(choice) {
		case 0:
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city LIMIT %d, %d;";
			break;
			
		case 1:
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city "
					+ "WHERE city_name like '%%" + search + "%%' LIMIT %d, %d;";
			break;
		
			
		default:
			System.out.println("검색조건 선택이 올바르지 않습니다.");
			sql = "SELECT seq, city_name, reg_date, edit_date "
					+ "FROM house_city "
					+ "WHERE seq=-1 LIMIT %d, %d;";
			break;
		}
			
		
		ResultSet rs = db.getResult(sql, start, end);
		
		if(rs != null) {
			// 데이터 조회 결과 있는 경우
			try {
				list = new ArrayList<HouseCityItem>();
				
				while(rs.next()) {
					
					// 1) ResultSet의 모든 데이터를 변수로 추출
					int city_seq = rs.getInt(1);
					String city_name = rs.getString(2);
					String reg_date = rs.getString(3);
					String edit_date = rs.getString(4);
					
					// 2) 추출된 값을 객체로 구성
					HouseCityItem item = new HouseCityItem(city_seq, city_name, reg_date, edit_date);
					
					// 3) ArrayList에 추가
					list.add(item);
				}
			} catch (SQLException e) {
				logger.error(e);
			} finally {
				// 4) 데이터 조회에 대한 메모리 반납
				try {
					rs.close();
				} catch (SQLException e) {}
				rs = null;
			}
		}
		
		if(list == null) {
			logger.error("데이터 조회 실패");
		} else {
			logger.debug("데이터 조회 성공 >> " + list.size() + "건 조회됨");
		}
		
		logger.debug("=============== method end >> listCity");
		
		return list;
	}
	
	/**
	 * 민박 도시 전체리스트 검색을 위한 오버로딩 정의
	 * @param choice						- 0으로 파라미터를 받을시 전체리스트 조회
	 * @return ArrayList<HouseCityItem>		- 0과 null을 오버로딩된 메서드로 반환
	 */
	public ArrayList<HouseCityItem> listCity(int choice) {
		return listCity(choice, null);
	}
	
	/**
	 * 민박 도시 전체리스트 검색을 위한 오버로딩 정의
	 * @param choice						- 0으로 파라미터를 받을시 전체리스트 조회
	 * @param start - 검색 범위의 시작위치
	 * @param end - 한 페이지에 보여질 글의 목록 수
	 * @return ArrayList<HouseCityItem>		- 0과 null을 오버로딩된 메서드로 반환
	 */
	public ArrayList<HouseCityItem> listCity(int choice, int start, int end) {
		return listCity(choice, null, start, end);
	}
}
